package site.wetsion.galio.sdk.strategy;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import site.wetsion.galio.sdk.common.GalioClientDetailsProperties;
import site.wetsion.galio.sdk.common.GalioOauthConstant;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * 抽象的token校验策略
 *
 * @author wetsion
 * @version 1.0
 * @CLassName AbstractTokenCheckStrategy
 * @date 2019/4/12 4:58 PM
 */
public abstract class AbstractTokenCheckStrategy {

    private final static Logger logger = LoggerFactory.getLogger(AbstractTokenCheckStrategy.class);

    private GalioClientDetailsProperties galioClientDetailsProperties;

    /**
     * 校验token
     *
     * @param token token值
     * @return com.alibaba.fastjson.JSONObject
     **/
    public abstract JSONObject checkToken(String token);

    protected JSONObject remoteCheckToken(String token) {
        JSONObject result = null;
        RestTemplate restTemplate = new RestTemplate();
        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        params.add(GalioOauthConstant.TOKEN, token);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.set(HttpHeaders.AUTHORIZATION,
                getBasicAuthString(galioClientDetailsProperties.getClientId(), galioClientDetailsProperties.getClientSecret(), null));
        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
        ResponseEntity<String> responseEntity;
        try {
            responseEntity = restTemplate.postForEntity(
                    galioClientDetailsProperties.getCheckTokenUrl(), entity, String.class);
            result = JSON.parseObject(responseEntity.getBody());
        } catch (Exception e) {
            logger.info("从远程auth校验认证: {} 失败: {}", token, e.getMessage());
            result = new JSONObject();
            result.put(GalioOauthConstant.ACTIVE, false);
        }
        return result;
    }

    private String getBasicAuthString (String username, String password, Charset charset) {
        Assert.notNull(username, "Username must not be null");
        Assert.notNull(password, "Password must not be null");
        if (charset == null) {
            charset = StandardCharsets.ISO_8859_1;
        }

        CharsetEncoder encoder = charset.newEncoder();
        if (!encoder.canEncode(username) || !encoder.canEncode(password)) {
            throw new IllegalArgumentException(
                    "Username or password contains characters that cannot be encoded to " + charset.displayName());
        }

        String credentialsString = username + ":" + password;
        byte[] encodedBytes = Base64.getEncoder().encode(credentialsString.getBytes(charset));
        String encodedCredentials = new String(encodedBytes, charset);
        return "Basic " + encodedCredentials;
    }

    public void setRmsClientDetailsProperties(GalioClientDetailsProperties galioClientDetailsProperties) {
        this.galioClientDetailsProperties = galioClientDetailsProperties;
    }
}
